#ifndef __ODBC_H__
#define __ODBC_H__

#include "stdafx.h"
#include "ddm.h"

namespace DDM
{
class DB_ODBC;
class ODBCException;
class ResultSet;
class ResultSetMetaData;

class ColInfo 
{
public:
    ColInfo() 
    {
        strcpy_s(title,"");
		decim_size = 0;
		nullable = 0;
		size = 0;
		type = 0;
    }
	TCHAR title[51];
	SQLSMALLINT type;
	unsigned int size;
	int decim_size;
	int nullable; // 0: NOT-NULL,1: NULL,2: NOT-KNOWN
};


class ResultSetMetaData 
{
private:
	int m_nNumCols;
	vector<ColInfo> m_vctCols;
public:
	ResultSetMetaData() { m_nNumCols = 0; }
	~ResultSetMetaData() { m_vctCols.clear(); }

    void SetColCnt(int n) { m_nNumCols = n; }
	int GetColCnt() { return m_nNumCols; }
	
    void AddColumn(ColInfo col) { m_vctCols.push_back(col); }
    ColInfo *GetColumn(size_t n)
	{ 
		if (n > m_vctCols.size()-1) 
            return NULL;
		return &m_vctCols[n];
	}
};

class ResultSet 
{
private:
	SQLHSTMT *m_hStmt;
	SQLUSMALLINT m_nRowStatusArray[10]; 

	SQLSMALLINT m_iRec;
	SQLTCHAR m_cState[6];
	SQLTCHAR m_cMsg[SQL_MAX_MESSAGE_LENGTH];
	SQLINTEGER m_nErr;
	SQLSMALLINT m_nMsg;

public:
	ResultSet(SQLHSTMT *stmt) 
	{
		m_hStmt = stmt;	
		SQLRETURN rc = SQLSetStmtAttr(*m_hStmt, SQL_ATTR_ROW_STATUS_PTR, m_nRowStatusArray, 0);
	}
	int GetColInfo(ResultSetMetaData *mtdt);

private:
	void HandleError();
};

class DB_ODBC : public Database
{
public:
	DB_ODBC();
    ~DB_ODBC();
    
	int connect(const char *host, const char *user, const char *passwd, const char *db=NULL);
    void close();
    
	int execute(const char* sql);
    int real_execute(const char* sql, vector<DBCol*> *cols);
    int execute_with_result(const char* sql, vector<DBRow*> *prows);

	int Commit();
	int Rollback();

	void SetTimeout(int n) {m_nConnTimeOut = n;}
	int GetTimeout() { return m_nConnTimeOut; }

    const char* db_error() const{return m_cMsg;}
    int GetLastErrNo() {return m_nErr;}

private:
    SQLHENV m_hEnv;
	SQLHDBC m_hDbc;
	SQLHSTMT m_hStmt;

	int m_nConnTimeOut; 

	SQLSMALLINT m_iRec;
	SQLTCHAR m_cState[6];
	char m_cMsg[SQL_MAX_MESSAGE_LENGTH];
	SQLINTEGER m_nErr;
	SQLSMALLINT m_nMsg;
	void HandleError(int type);
};

}
#endif